package com.xdcplus.web.service.bd.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.xdcplus.core.utils.BeanUtils;
import com.xdcplus.exceptions.XdcWebException;
import com.xdcplus.mom.constants.NumberConstant;
import com.xdcplus.mom.enums.ResponseEnum;
import com.xdcplus.mom.utils.ResponseUtils;
import com.xdcplus.mp.service.impl.BaseServiceImpl;
import com.xdcplus.mp.utils.PageableUtils;
import com.xdcplus.mp.utils.PropertyUtils;
import com.xdcplus.pager.vo.PageVO;
import com.xdcplus.system.api.DepartmentRemote;
import com.xdcplus.web.common.pojo.dto.bd.BdOpeDTO;
import com.xdcplus.web.common.pojo.dto.bd.BdOpeFilterDTO;
import com.xdcplus.web.common.pojo.entity.bd.BdOpe;
import com.xdcplus.web.common.pojo.entity.bd.BdPath;
import com.xdcplus.web.common.pojo.query.bd.BdOpeQuery;
import com.xdcplus.web.common.pojo.vo.bd.BdOpeByQaVO;
import com.xdcplus.web.common.pojo.vo.bd.BdOpeVO;
import com.xdcplus.web.mapper.bd.BdOpeMapper;
import com.xdcplus.web.service.bd.BdOpeService;
import com.xdcplus.web.service.bd.BdPathService;
import com.xdcplus.web.service.bd.BdPathiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工序管理(BdOpe)表服务实现类
 *
 * @author Fish.Fei
 * @since 2023-02-03 11:20:49
 */
@Slf4j
@Service("bdOpeService")
public class BdOpeServiceImpl extends BaseServiceImpl<BdOpeMapper, BdOpe, BdOpe, BdOpeVO> implements BdOpeService {

    @Autowired
    protected BdOpeMapper bdOpeMapper;

    @Autowired
    protected DepartmentRemote departmentRemote;

    @Autowired
    protected BdPathService bdPathService;

    @Autowired
    protected BdPathiService bdPathiService;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean saveBdOpe(BdOpeDTO bdOpeDTO) {
        Long codeCount = bdOpeMapper.selectCount(new QueryWrapper<BdOpe>()
                .eq("OPE_CODE", bdOpeDTO.getOpeCode())
                .or()
                .eq("OPE_NAME", bdOpeDTO.getOpeName())
        );
        Assert.isTrue(Validator.equal(codeCount,NumberConstant.ZERO.longValue()),
                ResponseEnum.CODE_OR_NAME_ALREADY_EXISTS.getMessage());

        BdOpe bdOpe = new BdOpe();
        BeanUtil.copyProperties(bdOpeDTO, bdOpe);
        bdOpe.setCreatedTime(new Timestamp(DateUtil.current()));
        
        return this.save(bdOpe);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean updateBdOpe(BdOpeDTO bdOpeDTO) {

        BdOpe bdOpe = this.getById(bdOpeDTO.getId());
        if (ObjectUtil.isNull(bdOpe)) {
            log.error("updateBdOpe() The BdOpe does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }

        Long codeCount = bdOpeMapper.selectCount(new QueryWrapper<BdOpe>()
                .ne("ID", bdOpeDTO.getId())
                .nested(
                        queryWrapper -> queryWrapper.eq("OPE_CODE", bdOpeDTO.getOpeCode())
                    .or()
                    .eq("OPE_NAME", bdOpeDTO.getOpeName())
                )

        );
        Assert.isTrue(Validator.equal(codeCount,NumberConstant.ZERO.longValue()),
                ResponseEnum.CODE_OR_NAME_ALREADY_EXISTS.getMessage());


        BeanUtil.copyProperties(bdOpeDTO, bdOpe);
        bdOpe.setUpdatedUser(bdOpeDTO.getUpdatedUser());
        bdOpe.setUpdatedTime(new Timestamp(DateUtil.current()));

        this.updateById(bdOpe);

        /// 清除序号
        if (ObjectUtil.isEmpty(bdOpeDTO.getOpeSeqNo())) {
            LambdaUpdateWrapper<BdOpe> bdOpeLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            bdOpeLambdaUpdateWrapper.eq(BdOpe::getId,bdOpeDTO.getId());
            bdOpeLambdaUpdateWrapper.set(BdOpe::getOpeSeqNo,"");
            if (ObjectUtil.isEmpty(bdOpeDTO.getCraftManufactureTime())) {
                bdOpeLambdaUpdateWrapper.set(BdOpe::getCraftManufactureTime,"");
            }
            if (ObjectUtil.isEmpty(bdOpeDTO.getCraftQTime())) {
                bdOpeLambdaUpdateWrapper.set(BdOpe::getCraftQTime,"");
            }
            this.update(bdOpeLambdaUpdateWrapper);
        }

        return true;
    }

    @Override
    public Boolean saveOrUpdateBatch(List<BdOpe> bdOpeList) {

        bdOpeList.forEach(bdOpe -> {
            BdOpe bdOpeParam = new BdOpe();
            bdOpeParam.setId(bdOpe.getId());
            if (ObjectUtil.isNotNull(bdOpe.getId())) {
                bdOpe.setId(bdOpe.getId());
                bdOpe.setUpdatedTime(new Timestamp(DateUtil.current()));
                LambdaUpdateWrapper<BdOpe> lambdaUpdate = Wrappers.lambdaUpdate();
                lambdaUpdate.eq(BdOpe::getId, bdOpe.getId());
                update(bdOpe, lambdaUpdate);
            } else {
                bdOpe.setCreatedTime(new Timestamp(DateUtil.current()));
                save(bdOpe);
            }
        });
        return true;
    }

    @Override
    public Boolean saveOrUpdateBatchByDTOList(List<BdOpeDTO> bdOpeDTOList) {

        List<BdOpe> bdOpeList = BeanUtils.copyProperties(bdOpeDTOList, BdOpe.class);
        return saveOrUpdateBatch(bdOpeList);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteBdOpeLogical(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
        BdOpe bdOpe = this.getById(id);

        if (ObjectUtil.isNull(bdOpe)) {
            log.error("deleteBdOpe() The BdOpe does not exist or has been deleted");
            throw new XdcWebException(ResponseEnum.ERROR);
        }
//        long bdPathiCount = bdPathiService.count(new QueryWrapper<BdPathi>().eq("FIRST_OPE_NO", bdOpe.getOpeCode()));
        long bdPathCrCount = bdPathService.count(new QueryWrapper<BdPath>().eq("CR_OPE_ID_FK", bdOpe.getId()));
//        Assert.isTrue(Validator.equal(bdPathiCount,NumberConstant.ZERO.longValue()),ResponseEnum.OPE_DELETE_FAILD_PATHI.getMessage());
        Assert.isTrue(Validator.equal(bdPathCrCount,NumberConstant.ZERO.longValue()),ResponseEnum.OPE_DELETE_FAILD_PATH.getMessage());

        return this.removeById(id);
    }
    
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean deleteBdOpeByIds(String ids) {
        Assert.notNull(ids, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());
        List<String> idList = Arrays.asList(ids.split(","));
        if(CollectionUtil.isEmpty(idList)){
           throw new XdcWebException(ResponseEnum.ERROR);
       }
        idList.forEach(id->{
            BdOpe bdOpe = this.getById(id);
            if (ObjectUtil.isNull(bdOpe)) {
                log.error("deleteBdOpe() The BdOpe does not exist or has been deleted");
                throw new XdcWebException(ResponseEnum.ERROR);
            }
        });

        return this.removeByIds(idList);
    }

    private List<BdOpe> queryBdOpeList(BdOpeFilterDTO bdOpeFilterDTO) {
        BdOpeQuery bdOpeQuery = BeanUtil.copyProperties(bdOpeFilterDTO, BdOpeQuery.class);
        /// 模糊查询关键字处理
        if (ObjectUtil.isNotEmpty(bdOpeQuery.getOpeCode())) {
            bdOpeQuery.setOpeCode(bdOpeQuery.getOpeCode().replaceAll("_","\\\\_"));
        }
        if (ObjectUtil.isNotEmpty(bdOpeQuery.getOpeName())) {
            bdOpeQuery.setOpeName(bdOpeQuery.getOpeName().replaceAll("_","\\\\_"));
        }
        return bdOpeMapper.queryBdOpe(bdOpeQuery);
    }

    @Override
    public List<BdOpeVO> queryBdOpeVOList(BdOpeFilterDTO bdOpeFilterDTO) {
        return this.objectConversion(queryBdOpeList(bdOpeFilterDTO));
    }

    @Override
    public PageVO<BdOpeVO> queryBdOpe(BdOpeFilterDTO bdOpeFilterDTO) {
        PageVO<BdOpeVO> pageVO = new PageVO<>();

        if (bdOpeFilterDTO.getCurrentPage() > NumberConstant.ZERO) {
            PageableUtils.basicPage(bdOpeFilterDTO.getCurrentPage(), bdOpeFilterDTO.getPageSize(),
                    "DESC NULLS LAST", "OPE_SEQ_NO");
        }else{
            PageableUtils.basicPage(1, NumberConstant.QUERY_MAX_DATA_SIZE,
                    "DESC NULLS LAST", "OPE_SEQ_NO");
        }

        List<BdOpe> bdOpeList = queryBdOpeList(bdOpeFilterDTO);
        PageInfo<BdOpe> pageInfo = new PageInfo<>(bdOpeList);
        PropertyUtils.copyProperties(pageInfo, pageVO, this.objectConversion(bdOpeList));

        return pageVO;
    }

    @Override
    public BdOpeVO queryBdOpeById(Long id) {

        Assert.notNull(id, ResponseEnum.THE_ID_CANNOT_BE_EMPTY.getMessage());

        return this.objectConversion(this.getById(id));
    }

    @Override
    public String getOpeNameById(Long id) {
        if(id==null){
            return null;
        }
        BdOpe bdOpe= this.getById(id);
        if(bdOpe!=null){
            return bdOpe.getOpeName();
        }
        return null;
    }

    @Override
    public String getOpeNameByOpeCode(String opeCode) {
        if(StrUtil.isEmpty(opeCode)){
            return null;
        }
        BdOpe BdOpe=bdOpeMapper.queryByOpeCode(opeCode);
        if(BdOpe!=null){
            return BdOpe.getOpeName();
        }
        return null;
    }

    @Override
    public List<BdOpeByQaVO> queryBdOpeByQa(BdOpeFilterDTO bdOpeFilterDTO) {
        BdOpeQuery bdOpeQuery = BeanUtil.copyProperties(bdOpeFilterDTO, BdOpeQuery.class);
        List<BdOpe> bdOpes = bdOpeMapper.queryBdOpeByQa(bdOpeQuery);
        if(CollectionUtil.isEmpty(bdOpes)){
            return null;
        }
        List<BdOpeByQaVO> bdOpeByQaVOS = CollectionUtil.newArrayList();
        BdOpeByQaVO bdOpeByQaVO;
        for (BdOpe bdOpe : bdOpes) {
            if(StrUtil.equalsAny(bdOpe.getOpeCode(),"TEX","KS","PECVD","ALD_Z","PRT")){
                bdOpeByQaVO = BeanUtil.copyProperties(bdOpe, BdOpeByQaVO.class);
                if (StrUtil.isNotEmpty(bdOpeByQaVO.getBoxUseCode())) {
                    List<String> boxUseCodes = Arrays.asList(bdOpeByQaVO.getBoxUseCode().replace("[", "")
                            .replace("]", "").replace("\"", "").split(","));
                    bdOpeByQaVO.setBoxUseCodes(boxUseCodes);
                }
                bdOpeByQaVOS.add(bdOpeByQaVO);
            }
        }

        return bdOpeByQaVOS;
    }

    @Override
    public List<BdOpeVO> findBdOpe(BdOpeFilterDTO bdOpeFilterDTO) {
        return this.objectConversion(queryBdOpeList(bdOpeFilterDTO));
    }

    @Override
    public List<BdOpeVO> getOpeByOpeCodes(List<String> opeCodeList) {
        LambdaQueryWrapper<BdOpe> bdOpeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bdOpeLambdaQueryWrapper.in(BdOpe::getOpeCode,opeCodeList);
        return this.list(bdOpeLambdaQueryWrapper).stream().map(bdOpe -> {
            BdOpeVO bdOpeVO = new BdOpeVO();
            BeanUtil.copyProperties(bdOpe,bdOpeVO);
            return bdOpeVO;
        }).collect(Collectors.toList());
    }


    @Override
    public BdOpeVO objectConversion(BdOpe s) {
        BdOpeVO bdOpeVO = super.objectConversion(s);
//        bdOpeVO.setToolGroupVO(toolGroupService.queryToolGroupById(bdOpeVO.getToolGroupIdFk()));
        bdOpeVO.setDepartmentVO(ResponseUtils.getResponse(departmentRemote.queryDepartmentById(bdOpeVO.getDeptIdFk())));

        return bdOpeVO;
    }

    @Override
    public List<BdOpeVO> objectConversion(List<BdOpe> sList) {
        if (!CollectionUtil.isNotEmpty(sList)) {
            return null;
        } else {
            List<BdOpeVO> tList = new ArrayList();
            Iterator var3 = sList.iterator();

            while(var3.hasNext()) {
                BdOpe s = (BdOpe)var3.next();
                BdOpeVO t = this.objectConversion(s);
                Optional.ofNullable(t).ifPresent(tList::add);
            }

            return tList;
        }
    }


    @Override
    public BdOpe queryByOpeCode(String opeCode) {
        return bdOpeMapper.queryByOpeCode(opeCode);
    }

    @Override
    public List<BdOpeVO> queryOpeCodesForOpeCode(String opeCode) {
        return bdPathService.queryOpeCodesForOpeCode(opeCode);
    }

}
